package com.easyadmin.pro.common.filters;

import com.easyadmin.pro.common.constants.SystemConstants;
import com.easyadmin.pro.common.enums.HttpCodeEnum;
import com.easyadmin.pro.common.vo.RestResult;
import com.easyadmin.pro.modules.sys.entity.UserEntity;
import com.easyadmin.pro.modules.sys.entity.UserRoleEntity;
import com.easyadmin.pro.modules.sys.mapper.UserRoleMapper;
import com.easyadmin.pro.modules.sys.vo.UserVo;
import com.easyadmin.pro.tool.ServletUtil;
import com.easyadmin.pro.tool.TokenUtils;
import com.mybatisflex.core.query.QueryWrapper;
import io.jsonwebtoken.Claims;
import jakarta.annotation.Resource;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * packageName com.easyadmin.pro.common.filters
 *
 * @author 骑着蚂蚁去上天
 * @version JDK 17
 * @className AuthenticationTokenFilter
 * @date 2024/4/1
 * @description token校验拦截器
 */
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class AuthenticationTokenFilter extends OncePerRequestFilter {

    private final RedisTemplate redisTemplate;

    private final UserRoleMapper userRoleMapper;

    @Value("${easy-admin-pro.not-login-address}")
    private String NOT_LOGIN_ADDRESS;

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {

        //获取token
        String token = request.getHeader("token");
        List<String> notLoginAddress = Arrays.asList(NOT_LOGIN_ADDRESS.split(","));
        if (notLoginAddress.contains(request.getRequestURI())) {
            //放行
            filterChain.doFilter(request, response);
            return;
        }
        if (!StringUtils.hasLength(token)) {
            ServletUtil.writeJson(RestResult.lose(HttpCodeEnum.TOKEN_NOT_FOUND));
            return;
        }
        Claims claims = TokenUtils.parse(token);
        if (Objects.isNull(claims)) {
            ServletUtil.writeJson(RestResult.lose(HttpCodeEnum.TOKEN_PARSING_EXCEPTION));
            return;
        }
        String userId = claims.getId();
        String redisKey = SystemConstants.LOGIN_PREFIX + userId;
        UserEntity userEntity = (UserEntity) redisTemplate.opsForValue().get(redisKey);
        if (Objects.isNull(userEntity)) {
            ServletUtil.writeJson(RestResult.lose(HttpCodeEnum.NEED_LOGIN));
            return;
        }
        UserRoleEntity userInfo = userRoleMapper
                .selectOneByQuery(new QueryWrapper().eq(UserRoleEntity::getUserId, userEntity.getId()));
        //存入SecurityContextHolder
        //获取权限信息封装到Authentication中
        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(new UserVo(userEntity, userInfo),null,null);
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        //放行
        filterChain.doFilter(request, response);
    }
}